package eu.webhib.frmwrk.servlet;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.log4j.Logger;

/**
 * Servlet Filter controlling and dispatching the incoming requests
 */
public class MainDispatcherFilter implements javax.servlet.Filter {

   private static final Logger log = Logger.getLogger(MainDispatcherFilter.class);

   class ResponseWrapper extends HttpServletResponseWrapper {

      public ResponseWrapper(HttpServletResponse response) {
         super(response);
      }

      @Override
      public String encodeURL(String url) {
         // make clean urls by stripping .xhtml and index.xhtml
         if (url.endsWith(".xhtml")) {
            int strip = 6;
            if (url.endsWith("index.xhtml")) {
               strip = 11;
            }
            String urlOut = url.substring(0, url.length() - strip);
            log.trace("encodeURL: " + url + " > " + urlOut);
            return urlOut;
         }
         return url;
      }
   }
   //
   private ServletContext servletContext;
   private String servletRealPath;
   //private static String pagesPath = "/WEB-INF/";
   private static String jsfPagesPath = "/";

   public MainDispatcherFilter() {
      log.info("Filter()");
   }

   @Override
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
           throws IOException, ServletException {

      // current servlet request
      HttpServletRequest httpRequest = (HttpServletRequest) request;
      // current requested URI
      String requestURI = httpRequest.getRequestURI();

      if (requestURI.lastIndexOf('.') != -1) {
         log.trace("getRequestURI(): " + requestURI);
         // has "." in the url, proceed with servlet selected
         log.trace("chain.doFilter()");
         chain.doFilter(request, response);
      } else {
         log.trace("getRequestURI(): " + requestURI);
         // have to use requestURI since getPathInfo() does not return anything within filter
         String pagePath = requestURI.substring(httpRequest.getContextPath().length() + 1);
         log.trace("pagePath: " + pagePath);
         // check for <pagePath>.xhtml file in filesystem
         String forwardTarget = jsfPagesPath + pagePath + ".xhtml";
         if (!new File(servletRealPath + forwardTarget).isFile()) {
            // forward to main view (index.html) with page parameter
            forwardTarget = jsfPagesPath + "index.xhtml?page=" + pagePath;
         }

         log.info("forward to: " + forwardTarget);
         try {
            request.getRequestDispatcher(forwardTarget).forward(request,
                    new ResponseWrapper((HttpServletResponse) response));
         } catch (ServletException ex) {
            if (ex.getCause() instanceof javax.faces.application.ViewExpiredException) {
               log.warn("ViewExpiredException - redirect to: " + httpRequest.getContextPath());
               ((HttpServletResponse) response).sendRedirect(httpRequest.getContextPath());
               return;
            }
            log.fatal(ex);
            throw ex;
         } catch (IOException ex) {
            log.fatal(ex);
            throw ex;
         }
         // deliver pagePath to application
         AbstractApplication.getInstance().setRequestFinished(httpRequest, pagePath);
      }
   }

   @Override
   public void init(FilterConfig filterConfig) {
      servletContext = filterConfig.getServletContext();
      // get filesystem base path this servlet is running in
      servletRealPath = servletContext.getRealPath("");
      log.info("servletRealPath: " + servletRealPath);
   }

   @Override
   public void destroy() {
   }
}
